1   /*
2    * Copyright (C) 2013 The Guava Authors
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.google.common.math;
18  
19  import com.google.caliper.BeforeExperiment;
20  import com.google.caliper.Benchmark;
21  import com.google.caliper.Param;
22  
23  import java.util.Random;
24  
25  /**
26   * Benchmarks for various ways of writing the expression {@code foo + ((bar < baz) ? 1 : 0)}.
27   *
28   * @author Louis Wasserman
29   */
30  public class LessThanBenchmark {
31    static final int SAMPLE_SIZE = 0x1000;
32    static final int SAMPLE_MASK = 0x0FFF;
33  
34    @Param("1234")
35    int randomSeed;
36  
37    int[] xInts;
38    int[] yInts;
39  
40    long[] xLongs;
41    long[] yLongs;
42  
43    int[] constant;
44    
45    private static final long NONNEGATIVE_LONG_MASK = 0x7FFFFFFFFFFFFFFFL;
46  
47    @BeforeExperiment
48    void setUp() {
49      Random random = new Random(randomSeed);
50      xInts = new int[SAMPLE_SIZE];
51      yInts = new int[SAMPLE_SIZE];
52      xLongs = new long[SAMPLE_SIZE];
53      yLongs = new long[SAMPLE_SIZE];
54      constant = new int[SAMPLE_SIZE];
55      for (int i = 0; i < SAMPLE_SIZE; i++) {
56        xInts[i] = random.nextInt(Integer.MAX_VALUE);
57        yInts[i] = random.nextInt(Integer.MAX_VALUE);
58        xLongs[i] = random.nextLong() & NONNEGATIVE_LONG_MASK;
59        yLongs[i] = random.nextLong() & NONNEGATIVE_LONG_MASK;
60        constant[i] = random.nextInt();
61      }
62    }
63  
64    @Benchmark int branchFreeLtIntInlined(int reps) {
65      int tmp = 0;
66      for (int i = 0; i < reps; i++) {
67        int j = i & SAMPLE_MASK;
68        int x = xInts[j];
69        int y = yInts[j];
70        int z = constant[j];
71        tmp += z + ((x - y) >>> (Integer.SIZE - 1));
72      }
73      return tmp;
74    }
75  
76    @Benchmark int branchFreeLtInt(int reps) {
77      int tmp = 0;
78      for (int i = 0; i < reps; i++) {
79        int j = i & SAMPLE_MASK;
80        int x = xInts[j];
81        int y = yInts[j];
82        int z = constant[j];
83        tmp += z + IntMath.lessThanBranchFree(x, y);
84      }
85      return tmp;
86    }
87  
88    @Benchmark int ternaryLtIntAddOutsideTernary(int reps) {
89      int tmp = 0;
90      for (int i = 0; i < reps; i++) {
91        int j = i & SAMPLE_MASK;
92        int x = xInts[j];
93        int y = yInts[j];
94        int z = constant[j];
95        tmp += z + ((x < y) ? 1 : 0);
96      }
97      return tmp;
98    }
99  
100   @Benchmark int ternaryLtIntAddInsideTernary(int reps) {
101     int tmp = 0;
102     for (int i = 0; i < reps; i++) {
103       int j = i & SAMPLE_MASK;
104       int x = xInts[j];
105       int y = yInts[j];
106       int z = constant[j];
107       tmp += (x < y) ? z + 1 : z;
108     }
109     return tmp;
110   }
111 
112   @Benchmark int branchFreeLtLongInlined(int reps) {
113     int tmp = 0;
114     for (int i = 0; i < reps; i++) {
115       int j = i & SAMPLE_MASK;
116       long x = xLongs[j];
117       long y = yLongs[j];
118       int z = constant[j];
119       tmp += z + (int) ((x - y) >>> (Long.SIZE - 1));
120     }
121     return tmp;
122   }
123 
124   @Benchmark int branchFreeLtLong(int reps) {
125     int tmp = 0;
126     for (int i = 0; i < reps; i++) {
127       int j = i & SAMPLE_MASK;
128       long x = xLongs[j];
129       long y = yLongs[j];
130       int z = constant[j];
131       tmp += z + LongMath.lessThanBranchFree(x, y);
132     }
133     return tmp;
134   }
135 
136   @Benchmark int ternaryLtLongAddOutsideTernary(int reps) {
137     int tmp = 0;
138     for (int i = 0; i < reps; i++) {
139       int j = i & SAMPLE_MASK;
140       long x = xLongs[j];
141       long y = yLongs[j];
142       int z = constant[j];
143       tmp += z + ((x < y) ? 1 : 0);
144     }
145     return tmp;
146   }
147 
148   @Benchmark int ternaryLtLongAddInsideTernary(int reps) {
149     int tmp = 0;
150     for (int i = 0; i < reps; i++) {
151       int j = i & SAMPLE_MASK;
152       long x = xLongs[j];
153       long y = yLongs[j];
154       int z = constant[j];
155       tmp += (x < y) ? z + 1 : z;
156     }
157     return tmp;
158   }
159 }